package cn.com.connected.base.aop;

import cn.com.connected.base.exception.BusinessException;
import cn.com.connected.base.exception.ErrorCode;
import cn.com.connected.base.exception.ErrorLogRobot;
import cn.com.connected.base.params.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.Serializable;
import java.util.stream.Collectors;


/**
 * 作者:   邵明生
 * 时间:   2017/11/14 20:21
 * 描述:  Controller 异常 统一处理
 */
@ControllerAdvice
@Slf4j
public class AdviceException implements Serializable {

	private static final Logger logger = LoggerFactory.getLogger(AdviceException.class);

	@Resource
	private ErrorLogRobot errorLogRobot;

	// 上传文件过大，捕获异常：MaxUploadSizeExceededException
	@ResponseBody
	@ExceptionHandler(MaxUploadSizeExceededException.class)
	public JsonResult handlerMaxUploadFile(MaxUploadSizeExceededException ex) {
		JsonResult<?> result = new JsonResult(null,ErrorCode.FILE_UPLOAD_BIG_ERROR);
		return result;
	}
	// 传入参数类型不匹配 如 Integer 传给 List
	@ResponseBody
	@ExceptionHandler(HttpMessageNotReadableException.class)
	public JsonResult handlerHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
		Throwable mostSpecificCause = ex.getMostSpecificCause();
		if (mostSpecificCause != null) {
			String exceptionName = mostSpecificCause.getClass().getName();
			String message = mostSpecificCause.getMessage();
			message = message.replace("Invalid date value","此值格式不对");
			JsonResult<?> result = new JsonResult(null,ErrorCode.PARAM_INVALID.getCode(),message);
			return result;
		}

		JsonResult<?> result = new JsonResult(null,ErrorCode.PARAM_INVALID);
		return result;
	}

	@ResponseBody
	@ResponseStatus(value = HttpStatus.OK)
	@ExceptionHandler(BusinessException.class)
	public JsonResult<Void> businessExceptionHandler(BusinessException e) {
		log.error(e.getMsg());

		//如果是需要跳出登录的，返回明确的状态码
		if (e.getCode()!=null && e.getCode().equals(ErrorCode.LOGIN_TIMEOUT.getCode())){
			return new JsonResult<>(null,e.getCode(),e.getMsg());
		}else{
			//非需要前端跳出登录的，返回统一的错误
			return new JsonResult<>(e);
		}
	}

	@ResponseBody
	@ResponseStatus(value = HttpStatus.OK)
	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	public JsonResult<Void> httpRequestMethodNotSupportedExceptionHandler(Exception e) {
		return new JsonResult<>(ErrorCode.METHOD_INVALID);
	}

	@ResponseBody
	@ResponseStatus(value = HttpStatus.OK)
	@ExceptionHandler(Exception.class)
	public JsonResult<Void> exceptionHandler(Exception e) {
		log.error(e.getMessage(), e);
		errorLogRobot.sendError2DingDing(ErrorLogRobot.formatStackTrace(e));
		return new JsonResult<>(ErrorCode.SYSTEM_FAIL);
	}

	/**
	 * @Description 处理参数验证异常 如 @RequestBody @Validated BaseSearchDto<OrganizationDto> searchParam
	 * @author 邵明生
	 * @date 2019/8/19 17:47
	 **/
	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseStatus(value = HttpStatus.OK)
	@ResponseBody
	public JsonResult exceptionError(MethodArgumentNotValidException e) {
		String errorMessage = e.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(","));
		JsonResult<?> result = new JsonResult(null,ErrorCode.PARAM_INVALID.getCode(),errorMessage);
		return result;
	}

	/**
	 * @Description 处理参数验证异常 如 @NotNull(message = "参数不能为空") @RequestParam Integer searchType
	 * @author 邵明生
	 * @date 2019/8/19 17:47
	 **/
	@ExceptionHandler(ConstraintViolationException.class)
	@ResponseStatus(value = HttpStatus.OK)
	@ResponseBody
	public JsonResult exceptionError2(ConstraintViolationException e) {
		String errorMessage = e.getConstraintViolations().stream().map(ConstraintViolation::getMessageTemplate).collect(Collectors.joining(","));
		JsonResult<?> result = new JsonResult(null,ErrorCode.PARAM_INVALID.getCode(),errorMessage);
		return result;
	}

}
